#pragma once
#include<iostream>
#include<string>
#include<list>
#include<memory>
#include<algorithm>
#include<sys/types.h>
#include<sys/socket.h>
#include"InetAddr.hpp"
#include"log.hpp"
#include"Thread.hpp"
class UserInterface{
    public:
        virtual ~UserInterface() = default;
        virtual void SendTo(int  sockfd, const std::string &message) = 0;
        virtual bool operator==(const InetAddr &other) = 0;
        virtual std::string Get_IpPort() = 0;
};

class User : public UserInterface{
    public:
        User(const InetAddr &id)
            :_id(id)
        {

        }
        void SendTo(int sockfd, const std::string &message) override
        {
            LOG(log_level::DEBUG)<<"send message to "<<_id.GetIpPort()<<" info "<<message;
            int n = ::sendto(sockfd, message.c_str(), message.size(), 0,(struct sockaddr*)_id.GetAddr(), _id.GetAddrLen());
        }
        bool operator==(const InetAddr &other) override
        {
            return _id == other;
        }
        std::string Get_IpPort() override
        {
            return _id.GetIpPort();
        }
        ~User()
        {

        }
    private:
        InetAddr _id;

};

//对用户消息进行路由
//把所有的用户先管理起来
//观察者模式observer
class UserManager{
    public:
        UserManager()
        {

        }
        bool AddUser(const InetAddr &id)
        {
            My_thread::LockGuard lock(_mutex);
            for(const auto &user: _online_user){
                if(*user == id){
                    LOG(log_level::DEBUG)<<id.GetIpPort()<<" user already exist ";
                    return false;
                }
            }
            LOG(log_level::DEBUG)<<"add user "<<id.GetIpPort();
            _online_user.push_back(std::make_shared<User>(id));
            // LOG(log_level::DEBUG)<<"user count "<<_online_user.size();
            ShowAllUser();  
            return true;
        }
        void DelUser(const InetAddr &user)
        {
            My_thread::LockGuard lock(_mutex);
            auto pos = std::remove_if(_online_user.begin(),_online_user.end(),[&user](const std::shared_ptr<UserInterface> u)->bool{return u->operator==(user);});
            _online_user.erase(pos,_online_user.end());
            ShowAllUser();
        }
        void Router(int sockfd,const std::string &message)//观察者模式
        {
            My_thread::LockGuard lock(_mutex);
            for(auto &user: _online_user){
                user->SendTo(sockfd, message);
            }
        }
        void ShowAllUser()
        {
            LOG(log_level::DEBUG)<<"show all onlineuser : num->"<<_online_user.size();
            for(auto &user: _online_user){
                LOG(log_level::DEBUG)<<user->Get_IpPort();
            }
        }
        ~UserManager()
        {

        }
        int GetUserCount() const
        {
            return _online_user.size();
        }
    private:
        std::list<std::shared_ptr<UserInterface>> _online_user;
        My_thread::Mutex _mutex;
};
